package com.android.hitch;

import java.io.*;
import java.util.List;
import com.android.hitch.googlemaps.*;
import com.android.hitch.network.*;

import android.app.Dialog;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.location.*;
import android.media.*;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.*;
import com.google.android.maps.*;

public class Hitch_androidActivity extends MapActivity implements LocationListener, HandlerClientIF{
	public Button btn_send;
	public TextView txtLayout;
	public EditText editText1;
	public Connection conn;
	public MapView map;
	public ImageButton btnMenu;
	public MyPositionOverlay positionOverlay;
	private static final int TWO_MINUTES = 1000 * 30 * 2;
	private boolean isGPSLoc = true;
	private PopupWindow pw;
	private PowerManager.WakeLock wl;
	/**
	 * Simple Dialog used to show the splash screen
	 */
	protected Dialog mSplashDialog;

	
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		MyStateSaver data = (MyStateSaver) getLastNonConfigurationInstance();
		if (data != null) {
	        // Show splash screen if still loading
	        if (data.showSplashScreen) {
	            showSplashScreen();
	        }
	        setContentView(R.layout.main);        
	 
	        // Rebuild your UI with your saved state here
	    } else {
	        showSplashScreen();
	        setContentView(R.layout.main);
	        // Do your heavy loading here on a background thread
	    }
		
		// Do not dim screen
		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "DoNotDimScreen");

		conn = new Connection("213.57.246.166", 5555);
		conn.AddHandler(this);
		conn.Connect();
		
		// Prevent Screen rotation.
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
		
		LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
		mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, this); 
		mlocManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 0, 0, this);  

		btn_send = (Button) findViewById(R.id.send_btn);
		txtLayout = (TextView) findViewById(R.id.txtLayout);
		editText1 = (EditText) findViewById(R.id.editText1);
		btnMenu = (ImageButton) findViewById(R.id.btnMenu);
		map = (MapView) findViewById(R.id.map);
		map.setBuiltInZoomControls(true);
		map.getController().setZoom(19);

		// Add the MyPositionOverlay
	    positionOverlay = new MyPositionOverlay();
	    List<Overlay> overlays = map.getOverlays();
	    overlays.add(positionOverlay);

		btn_send.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				if (conn.isConnected())
					try {
						conn.sendToServer(editText1.getText().toString().getBytes());
						editText1.setText("");
					} catch (IOException e) {
						Toast.makeText( getApplicationContext(), "Sending failed!", Toast.LENGTH_SHORT).show();
					}
			}
		});
		
		btnMenu.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				Toast.makeText( getApplicationContext(), "Sariiiiiiii menu :)", Toast.LENGTH_SHORT).show();
				if (pw == null  || !pw.isShowing())
					initiatePopupWindow();
				else
					pw.dismiss();
			}
		});
	}
	

	@Override
	public Object onRetainNonConfigurationInstance() {
	    MyStateSaver data = new MyStateSaver();
	    // Save your important data here
	 
	    if (mSplashDialog != null) {
	        data.showSplashScreen = true;
	        removeSplashScreen();
	    }
	    return data;
	}
	 
	/**
	 * Removes the Dialog that displays the splash screen
	 */
	protected void removeSplashScreen() {
	    if (mSplashDialog != null) {
	        mSplashDialog.dismiss();
	        mSplashDialog = null;
	    }
	}
	 
	/**
	 * Shows the splash screen over the full Activity
	 */
	protected void showSplashScreen() {
	    mSplashDialog = new Dialog(this, R.style.SplashScreen);
	    //mSplashDialog.setContentView(R.layout.splashscreen);
	    mSplashDialog.setCancelable(false);
	    mSplashDialog.show();
	 
	    // Set Runnable to remove splash screen just in case
	    final Handler handler = new Handler();
	    handler.postDelayed(new Runnable() {
	      //@Override
	      public void run() {
	        removeSplashScreen();
	      }
	    }, 3000);
	}
	
	 
	/**
	 * Simple class for storing important data across config changes
	 */
	private class MyStateSaver {
	    public boolean showSplashScreen = false;
	    // Your other important fields here
	}
/////////////////////////////////////////////////////////////////////////////////////////////	
	public void UpdateLayout(final String msg) {
		runOnUiThread(new Runnable() {public void run()
		{
			txtLayout.setText(txtLayout.getText() + "\r\n" + msg);

			Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
			if(alert == null){
				// alert is null, using backup
				alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
				if(alert == null){  // I can't see this ever being null (as always have a default notification) but just incase
					// alert backup is null, using 2nd backup
					alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);               
				}
			}
			Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), alert);
			r.play();
		}});
	}

	public void CenterMap(final Location loc) {
		runOnUiThread(new Runnable() {public void run()
		{
			int zoomLevel = map.getZoomLevel();
			GeoPoint point = new GeoPoint((int)(loc.getLatitude() * 1E6), (int)(loc.getLongitude() * 1E6));
			if (loc != null) {
				positionOverlay.setLocation(loc);
				map.getController().animateTo(point);
				map.getController().setZoom(zoomLevel);
			}
		}});
	}

	public void ShowToastMessage(final String msg) {
		runOnUiThread(new Runnable() {public void run()
		{
			Toast.makeText( getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
		}});
	}


	public void onLocationChanged(Location loc) {
		loc.getLatitude();
		loc.getLongitude();
		//String Text = "My current location is:\n" + "Latitude = " + loc.getLatitude() + "\nLongitude = " + loc.getLongitude();	 
		//CenterMap(loc);
		//ShowToastMessage(loc.getProvider());
		
		
		LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
		// Or use LocationManager.GPS_PROVIDER

		Location lastKnownLocation = mlocManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		Location lastKnownLocation1 = mlocManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
		if (lastKnownLocation == null || isBetterLocation(lastKnownLocation,lastKnownLocation1)) 
		{
			//if (isGPSLoc)
				Toast.makeText( getApplicationContext(), "Network Location", Toast.LENGTH_SHORT).show();
			CenterMap((isBetterLocation(lastKnownLocation1,loc)? loc : lastKnownLocation1));
			isGPSLoc = false;
		}
		else
		{
			//if (!isGPSLoc)
				Toast.makeText( getApplicationContext(), "GPS Location", Toast.LENGTH_SHORT).show();
			mlocManager.removeUpdates(this);
			CenterMap((isBetterLocation(lastKnownLocation,loc)? loc : lastKnownLocation));
			isGPSLoc = true;
		}
		
	}

	public void onProviderDisabled(String provider) {
		Toast.makeText( getApplicationContext(),"Gps Disabled, please turn it on!", Toast.LENGTH_SHORT ).show();
	}

	public void onProviderEnabled(String provider) {
		Toast.makeText( getApplicationContext(), "Gps Enabled!", Toast.LENGTH_SHORT).show();
	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
	}


	@Override
	protected boolean isRouteDisplayed() {	return false;  }

	@Override
	public void onBackPressed()
	{
		try {
			conn.closeConnection();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.exit(0);
	}
	
	/** Determines whether one Location reading is better than the current Location fix
	  * @param location  The new Location that you want to evaluate
	  * @param currentBestLocation  The current Location fix, to which you want to compare the new one
	  */
	protected boolean isBetterLocation(Location location, Location currentBestLocation) {
	    if (currentBestLocation == null) {
	        // A new location is always better than no location
	        return true;
	    }

	    // Check whether the new location fix is newer or older
	    long timeDelta = location.getTime() - currentBestLocation.getTime();
	    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
	    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
	    boolean isNewer = timeDelta > 0;

	    // If it's been more than two minutes since the current location, use the new location
	    // because the user has likely moved
	    if (isSignificantlyNewer) {
	        return true;
	    // If the new location is more than two minutes older, it must be worse
	    } else if (isSignificantlyOlder) {
	        return false;
	    }

	    // Check whether the new location fix is more or less accurate
	    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
	    boolean isLessAccurate = accuracyDelta > 0;
	    boolean isMoreAccurate = accuracyDelta < 0;
	    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

	    // Check if the old and new location are from the same provider
	    boolean isFromSameProvider = isSameProvider(location.getProvider(),
	            currentBestLocation.getProvider());

	    // Determine location quality using a combination of timeliness and accuracy
	    if (isMoreAccurate) {
	        return true;
	    } else if (isNewer && !isLessAccurate) {
	        return true;
	    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
	        return true;
	    }
	    return false;
	}

	/** Checks whether two providers are the same */
	private boolean isSameProvider(String provider1, String provider2) {
	    if (provider1 == null) {
	      return provider2 == null;
	    }
	    return provider1.equals(provider2);
	}

	public void OnMessageReceived(String message) {
		UpdateLayout(message);
	}

	public void OnConnectionClosed() {
		ShowToastMessage("Connection Closed!");
	}

	public void OnConnectionEstablished() {
		ShowToastMessage("Connection Established!");
	}

	public void OnConnectionException(Exception exception) {
		ShowToastMessage("Connection Exception:\n" + exception.toString());
	}

	public void OnConnectingException(Exception exception) {
		ShowToastMessage("Cannot connect to the remote host:\n" + exception.toString());
	}
	
	@Override
    protected void onPause() {
            super.onPause();
            wl.release();
    }

    @Override
    protected void onResume() {
            super.onResume();
            wl.acquire();
    }
    
    private void initiatePopupWindow() {
    	try {
            //We need to get the instance of the LayoutInflater, use the context of this activity
            LayoutInflater inflater = (LayoutInflater) Hitch_androidActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            //Inflate the view from a predefined XML layout
            View layout = inflater.inflate(R.layout.main_menu,
                    (ViewGroup) findViewById(R.id.popup_element));
            // create a 300px width and 470px height PopupWindow
            pw = new PopupWindow(layout, 350, 570, true);
            // display the popup in the center
            pw.showAtLocation(layout, Gravity.CENTER, 0, 0);
     
            Button closeButton = (Button)layout.findViewById(R.id.btnClose);
            closeButton.setOnClickListener(cancel_button_click_listener);
            
            Button exitButton = (Button)layout.findViewById(R.id.btnExit);
            exitButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				try {
					conn.closeConnection();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.exit(0);
				}
            });
     
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private OnClickListener cancel_button_click_listener = new OnClickListener() {
        public void onClick(View v) {
            pw.dismiss();
        }
    };
}

